#ifndef __TCPCONNECTION_H__
#define __TCPCONNECTION_H__

#include <cstring>
#include <memory>
#include <string>
#include <sys/socket.h>
#include "buffer.h"
#include "channel.h"
#include "Base/callback.h"
#include "Base/noncopyable.h"
#include "Http/httpcontent.h"

namespace tiny_muduo
{
    class EventLoop;

    class TcpConnection : public std::enable_shared_from_this<TcpConnection>, NonCopyable
    {
    public:
        enum ConnectionState
        {
            kConnected,
            kDisconnected
        };

        TcpConnection(EventLoop* loop, int connfd);
        ~TcpConnection();

        void SetConnectionCallback(const ConnectionCallback& callback)
        {
            connection_callback_ = callback;
        }

        void SetConnectionCallback(ConnectionCallback&& callback)
        {
            connection_callback_ = std::move(callback);
        }

        void SetMessageCallback(const MessageCallback& callback)
        {
            message_callback_ = callback;
        }

        void SetMessageCallback(MessageCallback&& callback)
        {
            message_callback_ = std::move(callback);
        }

        void SetCloseCallback(const CloseCallback& callback)
        {
            close_callback_ = callback;
        }

        void SetCloseCallback(CloseCallback&& callback)
        {
            close_callback_ = std::move(callback);
        }

        void ConnectionEstablished()
        {
            state_ = kConnected;
            channel_->EnableReading();
            connection_callback_(shared_from_this(), &input_buffer_);
        }

        void Shutdown();
        bool IsShutdown() const { return shutdown_state_; }
        void ConnectionDestructor();
        void HandleClose();
        void HandleMessage();
        void HandleWrite();
        void Send(Buffer* buffer);
        void Send(const std::string& str);
        void Send(const char* message, int len);
        void Send(const char* message) { Send(message, strlen(message)); }

        inline HttpContent* GetHttpContent() { return &content_; }

        int fd() const { return fd_; }
        EventLoop* loop() const { return loop_; }

    private:
        EventLoop* loop_;
        int fd_;
        ConnectionState state_;
        std::unique_ptr<Channel> channel_;
        Buffer input_buffer_;
        Buffer output_buffer_;
        HttpContent content_;
        bool shutdown_state_;

        ConnectionCallback connection_callback_;
        MessageCallback message_callback_;
        CloseCallback close_callback_;
    };

    typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;
}
#endif
